use bytes::BytesMut;
use std::cmp::Ordering;
use std::fmt::Debug;
use std::fmt::Display;
use tools::error::buf_err::ToBufError;
use tools::types::bufs::ToBuf;
use tools::utils::byte::str_from_utf8_bytes;

///用来保存str指针的结构.因为str是一个胖指针,有两个usize大小..直接用*const str无法完全表示...
/// 所以在这里使用此结构进行保存
#[derive(Clone, PartialEq, Eq)]
pub struct StrPtr(usize, usize);

impl StrPtr {
	#[inline]
	pub(crate) fn as_bytes(&self) -> &[u8] {
		unsafe { std::mem::transmute((self.0, self.1)) }
	}

	#[inline]
	pub fn as_str<'a>(&'a self) -> &'a str {
		let s: &str = str_from_utf8_bytes(self.as_bytes());

		s
	}

	#[inline]
	pub fn from_str(str: &str) -> Self {
		let (a, b) = unsafe { std::mem::transmute(str) };
		Self(a, b)
	}

	#[inline]
	pub fn from_bytes(bytes: &[u8]) -> Self {
		let (a, b) = unsafe { std::mem::transmute(bytes) };
		Self(a, b)
	}
}
impl Debug for StrPtr {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		f.write_str(self.as_str())
	}
}

impl Display for StrPtr {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		f.write_str(self.as_str())
	}
}

impl ToBuf for StrPtr {
	type Target = BytesMut;

	#[inline]
	fn write_to(&self, target: &mut Self::Target) -> Result<(), ToBufError> {
		target.extend_from_slice(self.as_bytes());

		Ok(())
	}
}

impl PartialOrd for StrPtr {
	#[inline]
	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
		self.as_bytes().partial_cmp(other.as_bytes())
	}
}

impl Ord for StrPtr {
	#[inline]
	fn cmp(&self, other: &Self) -> Ordering {
		self.as_bytes().cmp(other.as_bytes())
	}
}
